/**
 * 
 */
package com.taobao.service.impl;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Map;

import org.apache.commons.codec.binary.Base64;

import com.taobao.api.TaobaoApiException;
import com.taobao.api.direct.TaobaoDirectJsonRestClient;
import com.taobao.service.SessionService;

/**
 * @author hujingfei.pt@taobao.com
 *
 */
public class SessionServiceImpl implements SessionService {

	private String testUrl;
	private String appkey;
	private String secret;
	private String loginAddress;
	private TaobaoDirectJsonRestClient client;
	
	
	private String session;
	private String name;
	
	public final static String CONSTANT_NUMBER = "300";
	
	
	/**
	 * Default constructor
	 */
	public SessionServiceImpl(){	}
	
	/**
	 * Return the login name of the user 
	 * 
	 * @return if there is a login name in the session object, return it, or return null
	 */
	public String getLoginName() {
		return name;
	}
	
	/**
	 * Passing several essential parameters to the back-end.
	 * 
	 * @param url the url used to access the TOP api
	 * @param app the key of the application
	 * @param secrt the password of the application
	 * @param loginAddress the url used to login
	 * @return if initialized successfully, return true, or return false
	 * @throws Exception when some services behind back-end is unavailable, throw exceptions
	 */
	public boolean init(String url, String app, String secrt, String loginAddress) throws Exception {
		this.testUrl = url;
		this.appkey = app;
		this.secret = secrt;
		this.loginAddress = loginAddress;

		try {
			if (client == null) {
				client = new TaobaoDirectJsonRestClient(CONSTANT_NUMBER, this.testUrl, this.appkey, this.secret);
			}
			System.out.println("SessionServiceImpl::init:: Succeed");
			return true;
		} catch (TaobaoApiException e) {
			e.printStackTrace();
			throw e;
		}
	}

	/**
	 * Return the client object
	 * 
	 * @return the client object
	 */
	public TaobaoDirectJsonRestClient getClient() {
		return client;
	}
	
	/**
	 * Decode login name from topParameters and store it and session
	 * 
	 * @param session the session
	 * @param topParameters parameters encoded
	 */
	public String setSession(String session, String topParameters) {
		// Decoding
		try {
			topParameters = URLDecoder.decode(topParameters, "UTF8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		
		byte[] decodeBase64 = Base64.decodeBase64(topParameters.getBytes());
		// Construct redirect URL
		String redirectUrl = new String(decodeBase64);

		String name = extractParam(redirectUrl, "visitor_nick=");
		
		// Store.
		this.session = session;
		this.name = name;
		
		return name;
	}
	
	/**
	 * Get the login url
	 * 
	 * @param domain the domain of the callback url.
	 * @param url the callback url
	 */
	public String getLoginURL(String domain, String url) {

		String action = "post";
		String isExtShop = "true";
		String from = "top";
		String extShopDomain = domain;
		String Domain = "top";
		String extShopTitle = "top";
		String tg = url;

		StringBuffer buffer = new StringBuffer();
		buffer.append("appkey=" + appkey);
		buffer.append("&action=" + action);
		buffer.append("&isextshop=" + isExtShop);
		buffer.append("&from=" + from);
		buffer.append("&extShopTitle=" + extShopTitle);
		buffer.append("&extShopDomain=" + extShopDomain);
		buffer.append("&Domain=" + Domain);
		buffer.append("&tg=" + tg);

		return loginAddress + buffer.toString();
	}
	
	/**
	 * The user logout
	 * 
	 * @param url the callback url
	 * @param domain the domain
	 * @return
	 */
	public String logout(String domain, String url) {
		String action = "logoff";
		String isextshop = "true";
		String tg = url;

		StringBuffer buffer = new StringBuffer();
		buffer.append("appkey=" + appkey);
		buffer.append("&action=" + action);
		buffer.append("&isextshop=" + isextshop);
		buffer.append("&tg=" + tg);

		return loginAddress + buffer.toString();
	}
	
	/**
	 * Get the session of the user
	 * 
	 * @param userName the user name
	 * @param password the user password
	 * @return the session id(key)
	 * @throws Exception when some services behind back-end is unavailable, throw exceptions
	 */
	public String getSession(String userName, String password) throws Exception {
		return this.session;
	}
	
	/**
	 * Return the session id(key)
	 * 
	 * @return if there is a session key in the session object, return it, or return null
	 */
	public String getSession() {
		return this.session;
	}
	
	public String getUrl(Map<String, String> params) {
		params.put("nick", getLoginName());
		return UrlMaker.getUrl(params, appkey, secret, session);
	}
	
	/**
	 * Extract the value of the specified key from the query string part of the url.
	 * 
	 * @param queryString the query string. 
	 * @param key the key of the pair.
	 * @return If the key is found, return the value, or return null.
	 */
	private String extractParam(String queryString, String key) {
		int index1 = queryString.indexOf(key);
		if (index1 != -1) {
			index1 = index1 + key.length();
			int index2 = queryString.indexOf('&', index1);
			if (index2 == -1) {
				index2 = queryString.length();
			}
			return queryString.substring(index1, index2);
		}
		return null;
	}

}
